package com.opal.modules.costReportForm.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opal.consts.CommonConst;
import com.opal.consts.WSC;
import com.opal.domain.R;
import com.opal.domain.ReturnMessageData;
import com.opal.model.DataGridData;
import com.opal.modules.costReportForm.entity.*;
import com.opal.modules.costReportForm.entity.table.CostApprovals;
import com.opal.modules.costReportForm.entity.table.CostApprovalsExample;
import com.opal.modules.costReportForm.exception.CostReportUploadException;
import com.opal.modules.costReportForm.exception.DeleteCostReportException;
import com.opal.modules.costReportForm.mapper.mysql.*;
import com.opal.modules.costReportForm.model.CartonPriceDetailsRecord;
import com.opal.modules.costReportForm.model.CostReportData;
import com.opal.modules.costReportForm.service.ApprovalTaskService;
import com.opal.modules.costReportForm.service.CartonDetailsService;
import com.opal.modules.costReportForm.service.CostReportService;
import com.opal.system.entity.table.OpalUser;
import com.opal.system.service.OpalUserService;
import com.opal.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.security.auth.Subject;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class CostReportServiceImpl implements CostReportService {
    @Autowired
    private CostReportMapper costReportMapper;
    @Autowired
    private CostReportAMapper costReportAMapper;
    @Autowired
    private CostReportBMapper costReportBMapper;
    @Autowired
    private CostReportCMapper costReportCMapper;
    @Autowired
    private CostReportBSinglehoursMapper costReportBSinglehoursMapper;
    @Autowired
    private ApprovalTaskService approvalTaskService;
    @Autowired
    private CostApprovalsMapper costApprovalsMapper;
    @Autowired
    private OpalUserService opalUserService;
    @Autowired
    private CostReportOtherMapper costReportOtherMapper;
    @Autowired
    private CartonDetailsService cartonDetailsService;
    @Autowired
    private CostCommonMapper costCommonMapper;

    @Override
    public R costReportUploadFile(MultipartFile file) throws IOException {
        //获取文件后缀
        String fileName = file.getOriginalFilename();  //文件名字 主要获取后缀
        String split = fileName.split("\\.")[1];  //Java中小数点是一个特殊符号

        boolean flag=true;
        //判断后缀
        String[] suffixs={"JPEG","jpg","gif","png","TIFF"};
        for (String s:suffixs){
            if (split.equalsIgnoreCase(s)){
                flag=false;
            }
        }
        if (flag){
            throw new CostReportUploadException(1,"文件格式不支持");
        }

        //重命名：根据时间-精确到毫秒命名
        SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String format = simpleDateFormat.format(new Date());
        fileName=format+"."+split;     //获取最终文件名字

        //注意：这个是获取到springboot的class类加载路径，上传到这个路劲，由于是热部署监听到了文件变化会自动重启
        //String path = CostReportInitialInfo.class.getClassLoader().getResource("").getPath();
        //System.out.println("springboot的根路径："+path);
        log.info("System.getProperty(\"user.dir\")路径是啥？："+ CommonConst.SYSTEM_PATH); //F:\project\opal

        //获取最终服务目录：\fileServer\image\z\i\k\a\ 反斜杠和正斜杠可交互使用，在谷歌浏览器和火狐是可以的

        //把上传的文件输出到临时文件中
        byte[] bytes= new byte[2048];
        InputStream input = file.getInputStream();
        FileOutputStream fileOutputStream = new FileOutputStream(CommonConst.SYSTEM_PATH+"\\temp\\"+fileName);
        int i=0;
        while ((i=input.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,i);
        }
        fileOutputStream.close();
        input.close();
        //把文件名返回前端进行保存在costImagePath字段中，保存操作的时候转到真正的文件服务器中
        return new R(WSC.RESTPONSE_OK, fileName);
    }

    @Override
    public R deleteCostReportUploadFile(String filePath) {   //单纯的删除文件而已
        //filePath=\fileServer\image\b\d\o\r\202010300940000056.jpg
        if (!StringUtils.isBlank(filePath)){
            String property = CommonConst.SYSTEM_PATH+filePath; //F:/project/opal;window系统反斜杠和正斜杠可以交互用的
            File file=new File(property);
            if (file.exists()){
                file.delete();
            }
        }

        return new R(WSC.RESTPONSE_OK,CommonConst.SUCCESSMESSAGE);
    }

    private CostReport fileToFileServer(CostReport costReport) throws IOException {
        //判断若为null或空，证明用户没有传入图片
        String fileName = costReport.getCostImagePath(); //获取文件名 ---进行了添加/更换就只是文件名，
        if (StringUtils.isBlank(fileName)||fileName.contains(CommonConst.COST_FILE_SERVER_PATH)){//fileName.contains(CommonConst.COST_FILE_SERVER_PATH)包含这个路径证明是已经保存的路径
            return costReport;
        }
        //获取最终服务目录：\fileServer\image\z\i\k\a\ 反斜杠和正斜杠可交互使用，在谷歌浏览器和火狐是可以的
        String sonDir="abcdefghijklmnopqrstuvwxyz";
        char[] chars = sonDir.toCharArray();
        Random random= new Random();
        String somPath="\\";    // \z\i\k\a\
        int n=random.nextInt(5);   //随机获取要循环的次数 0-4
        for (int i = 0; i <=n; i++) {
            int j=random.nextInt(26);//0-25     // 随机获取目录名称
            somPath+=chars[j]+"\\";
        }
        somPath=CommonConst.COST_FILE_SERVER_PATH+somPath;  //\fileServer\image\z\i\k\a\
        //获取要存放的目录：未打包成jar包路径是在：CommonConst.SYSTEM_PATH=F:\project\opal：证明是在opal-start同级目录
        String path=CommonConst.SYSTEM_PATH + somPath;
        File fp = new File(path);
        if (!fp.exists()){
            fp.mkdirs();// 创建所有的路径
        }
        File f= new File(fp,fileName);
        if (!f.exists()){
            f.createNewFile(); //创建文件
        }
        String servePath=somPath+fileName; //要保存到数据库的路径--返回前端进行保存

       //把临时文件转到文件服务器中
        File file= new File(CommonConst.SYSTEM_PATH+"\\temp\\"+fileName); //从临时文件中获取文件流
        if (file.exists()){
            FileInputStream input = new FileInputStream(file);
            //把上传的文件输出到指定的文件夹下
            byte[] bytes= new byte[2048];

            FileOutputStream fileOutputStream = new FileOutputStream(f);
            int i=0;
            while ((i=input.read(bytes))!=-1){
                fileOutputStream.write(bytes,0,i);
            }
            fileOutputStream.flush();
            fileOutputStream.close();
            input.close();
        }else {
            log.error("临时文件中未找到文件！");
        }

        costReport.setCostImagePath(servePath);// 最终uri全路径的文件
        return costReport;
    }

    @Override//新增成本报告表：保存,成本报告状态为0、
    @Transactional(value = "mysqlTransactionManager",rollbackFor = {IOException.class,RuntimeException.class})
    public ReturnMessageData costReportSave(CostReport costReport, CostReportData costReportData) {

        //把临时文件中的数据转到文件服务器中并封装全路径的文件
        try {
            costReport= this.fileToFileServer(costReport);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CostReportUploadException(2,"图片保存失败！");
        }
        String costReportId = costReport.getCostReportId();
        try {
            CostReport result = costReportMapper.selectByPrimaryKey(costReportId);
            //0、前提条件判断
            costReportPremiseDeal(result,costReportData.getProcessKey_());

            //1、把字符串数组转换为list对象集合
            Map<String, Object> map = dataConversion(costReportData);

            int i ;

            //2021年1月19日处理物料编码 finished_product_code   ---finished_product_code2合并拆分到一个字段中：后续此字段用于查询用
            this.processingFinishedProductCodeData(costReport);

            //判断成本报告版本是否存在,存在插入，不存在修改
            if (result == null) {
                //插入数据:插入主表
                costReport.setUserId(UserUtils.getSessionUserId());

                i = costReportMapper.insertSelective(costReport);
            } else {
                i = costReportMapper.updateByPrimaryKeySelective(costReport);
            }
            if (i > 0) {
                List<CostReportA> costReportA = (List<CostReportA>) map.get("costReportA");
                if (costReportA !=null && costReportA.size() > 0) {
                    //先删除后添加不能判断，新增删除操作为0
                    costReportAMapper.deleteByCostReportId(costReportId);
                    this.costReportAdd(costReportA, costReportId);
                }
                List<CostReportB> costReportB = (List<CostReportB>) map.get("costReportB");
                if (costReportB !=null && costReportB.size() > 0) {
                    costReportBMapper.deleteByCostReportId(costReportId);
                    this.costReportBAdd(costReportB, costReportId);
                }
                List<CostReportC> costReportC = (List<CostReportC>) map.get("costReportC");
                if (costReportC !=null && costReportC.size() > 0) {
                    costReportCMapper.deleteByCostReportId(costReportId);
                    this.costReportCAdd(costReportC, costReportId);
                }
                List<CostReportBSinglehours> costReportBSinglehours = (List<CostReportBSinglehours>) map.get("costReportBSinglehours");
                if (costReportBSinglehours !=null && costReportBSinglehours.size() > 0) {
                    costReportBSinglehoursMapper.deleteByCostReportId(costReportId);
                    this.costReportBSinglehoursAdd(costReportBSinglehours, costReportId);
                }
                List<CostReportBOther> costReportBotherExpens = (List<CostReportBOther>) map.get("costReportBotherExpenses");
                if (costReportBotherExpens !=null && costReportBotherExpens.size() > 0) {
                    //根据成本报告删除
                    costReportOtherMapper.deleteCostReportBotherByCostReportId(costReportId);
                    //添加
                    this.costReportBotherExpensesAdd(costReportBotherExpens,costReportId);
                }
                List<CartonPriceDetailsRecord> cartonPriceDetailsRecord = (List<CartonPriceDetailsRecord>) map.get("cartonPriceDetailsRecords");
                if (cartonPriceDetailsRecord !=null && cartonPriceDetailsRecord.size() > 0) {
                    cartonDetailsService.deleteCartonPriceDetailsRecordService(costReportId,1);
                    cartonDetailsService.insertCartonPriceDetailsRecordService(cartonPriceDetailsRecord,costReportId);
                }
                List<CartonPriceDetailsRecord> cartonPriceDetailsRecordK = (List<CartonPriceDetailsRecord>) map.get("cartonPriceDetailsRecordsK");
                if (cartonPriceDetailsRecordK !=null && cartonPriceDetailsRecordK.size() > 0) {
                    cartonDetailsService.deleteCartonPriceDetailsRecordService(costReportId,2);
                    cartonDetailsService.insertCartonPriceDetailsRecordService(cartonPriceDetailsRecordK,costReportId);
                }

            }
            return new ReturnMessageData(WSC.RESTPONSE_OK,"成本报告【"+costReportId+"】:"+ CommonConst.SUCCESSMESSAGE);
        } catch (IOException e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.info("转换数据发生错误！");
            return  new ReturnMessageData(WSC.REQUEST_ERROR, "填写的数据有误！");
        } catch (RuntimeException e){
            e.printStackTrace();
            return new ReturnMessageData(WSC.REQUEST_ERROR, e.getMessage());
        }
    }

    public void processingFinishedProductCodeData(CostReport costReport) {
        StringBuilder stringBuilder = new StringBuilder();
        String finishedProductCode = costReport.getFinishedProductCode();
        String finishedProductCode2 = costReport.getFinishedProductCode2();  //兆婷的要求的物料编码
        //finishedProductCode2的数据W521007856，W521007871~W521007880,W521007978,W521007979
        if (!StringUtils.isBlank(finishedProductCode2)) {
            //判断
            String finishedProductCode3="";
            if ((finishedProductCode2.split(","))[0].indexOf("~") ==-1){
                 finishedProductCode3=finishedProductCode+"~"+finishedProductCode2;
            }else {
                 finishedProductCode3=finishedProductCode+","+finishedProductCode2;
            }


            String[] split = finishedProductCode3.split(",");

            for (String s : split) {
                String[] sp = s.split("~");
                if (sp.length > 0) {
                    //处理带~的数据；W521007871~W521007880
                    processing(stringBuilder, sp);
                } else {
                    //没有的直接封装
                    stringBuilder.append(s);
                }

            }

        }else {
            stringBuilder.append(finishedProductCode);
        }
        costReport.setFinishedProductCode3(stringBuilder.toString());
    }

    private void processing(StringBuilder stringBuilder, String[] sp) {

        String s0 = sp[0];
        if (sp.length>1){
            String s1 = sp[1];
            //获取长度 :补0用
            int length = s0.length();
            //截取前面三位数，保存截取到的前头
            String sub = s0.substring(0, 4);//W521
            Integer n0=null;
            Integer n1=null;
            try {
                n0= Integer.parseInt(s0.substring(4)); //转换会把前面的00去除掉
                n1= Integer.parseInt(s1.substring(4));
            }catch (RuntimeException e){
                throw new RuntimeException("保存失败:1、物料编码格式没有按要求进行操作，2、成品编码名称不对：不能纯中文或英文--后4位必须为数字");
            }

            //n0=7871;n1=7880
            Integer len=n1-n0;
            if (len<0){  //用户是反过来的操作：code1=108;code=103
                jiSuan(Math.abs(len),n1,stringBuilder,sub,length);
            }else {
                jiSuan(len,n0,stringBuilder,sub,length);
            }

        }else {
            stringBuilder.append(s0);
        }

    }

    private void jiSuan(Integer len, Integer n, StringBuilder stringBuilder,String sub,Integer length){
        for (int i=0;i<=len; i++){
            String r=sub+(n+i);
            //补0操作
            int rlen = length-r.length();
            if(rlen>0){
                for (int j=0;j<rlen; j++){
                    sub=sub+0;
                }
            }
            //获取到最终要的数据
            String resultSub = sub + (n + i);
            stringBuilder.append(resultSub);
        }
    }

    //新增成本报告表：保存并直接提交
    @Override
    @Transactional(value = "mysqlTransactionManager")
    public Object costReportSaveAuditService(CostReport costReport,CostReportData costReportData) throws Exception {
        //把临时文件中的数据转到文件服务器中并封装全路径的文件
        try {
            costReport= this.fileToFileServer(costReport);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CostReportUploadException(2,"图片保存失败！");
        }
        String costReportId = costReport.getCostReportId();
        CostReport result = costReportMapper.selectByPrimaryKey(costReportId);
        //0、前提条件判断
        costReportPremiseDeal(result, costReportData.getProcessKey_());

        //1、把字符串数组转换为list对象集合
        Map<String, Object> map = dataConversion(costReportData);
        List<CostReportA> costReportA = (List<CostReportA>) map.get("costReportA");
        List<CostReportB> costReportB = (List<CostReportB>) map.get("costReportB");
        List<CostReportC> costReportC = (List<CostReportC>) map.get("costReportC");
        List<CostReportBSinglehours> costReportBSinglehours = (List<CostReportBSinglehours>) map.get("costReportBSinglehours");

        //2、插入数据:先插入子表：启动流程需要改变状态，不然插不进去数据
        if (costReportA != null && costReportA.size() > 0) {
            //先删除所有后添加：不能判断：如果新增呢
            costReportAMapper.deleteByCostReportId(costReportId);
            this.costReportAdd(costReportA, costReport.getCostReportId());
        }
        if (costReportB != null && costReportB.size() > 0) {
            costReportBMapper.deleteByCostReportId(costReportId);
            this.costReportBAdd(costReportB, costReport.getCostReportId());
        }
        if (costReportC != null && costReportC.size() > 0) {
            costReportCMapper.deleteByCostReportId(costReportId);
            this.costReportCAdd(costReportC, costReport.getCostReportId());
        }
        if (costReportBSinglehours !=null && costReportBSinglehours.size() > 0) {
            costReportBSinglehoursMapper.deleteByCostReportId(costReportId);
            this.costReportBSinglehoursAdd(costReportBSinglehours, costReport.getCostReportId());
        }
        List<CostReportBOther> costReportBotherExpens = (List<CostReportBOther>) map.get("costReportBotherExpenses");
        if (costReportBotherExpens !=null && costReportBotherExpens.size() > 0) {
            //根据成本报告删除
            costReportOtherMapper.deleteCostReportBotherByCostReportId(costReportId);
            //添加
            this.costReportBotherExpensesAdd(costReportBotherExpens,costReportId);
        }
        List<CartonPriceDetailsRecord> cartonPriceDetailsRecord = (List<CartonPriceDetailsRecord>) map.get("cartonPriceDetailsRecords");
        if (cartonPriceDetailsRecord !=null && cartonPriceDetailsRecord.size() > 0) {
            cartonDetailsService.deleteCartonPriceDetailsRecordService(costReportId,1);
            cartonDetailsService.insertCartonPriceDetailsRecordService(cartonPriceDetailsRecord,costReportId);
        }
        List<CartonPriceDetailsRecord> cartonPriceDetailsRecordK = (List<CartonPriceDetailsRecord>) map.get("cartonPriceDetailsRecordsK");
        if (cartonPriceDetailsRecordK !=null && cartonPriceDetailsRecordK.size() > 0) {
            cartonDetailsService.deleteCartonPriceDetailsRecordService(costReportId,2);
            cartonDetailsService.insertCartonPriceDetailsRecordService(cartonPriceDetailsRecordK,costReportId);
        }

        //插入主表并启动流程
        costReportSave(costReport, costReportData.getProcessKey_(), result);

        return new ReturnMessageData(WSC.RESTPONSE_OK, "成本报告【" + costReportId + "】:已提交审核");
    }

    //成本报告表：启动流程、改变报告状态
    public void costReportSave(CostReport costReport,String processKey_,CostReport result) throws Exception {

        //2021年1月19日处理物料编码 finished_product_code   ---finished_product_code2合并拆分到一个字段中：后续此字段用于查询用
        this.processingFinishedProductCodeData(costReport);

        OpalUser user = UserUtils.getSessionUser();
        costReport.setCostReportStatus(3);               //把成本报告状态改为审核中
        costReport.setUserId(user.getUserId());         //申请人当前用户id
        int resultVO = 0;
        if (result == null) {
            resultVO = costReportMapper.insertSelective(costReport);
            log.info("用户: " + user.getUserName() + " 新增了 " + resultVO + " 条成本报告表!");
        } else {
            resultVO = costReportMapper.updateByPrimaryKeySelective(costReport);
            log.info("用户: " + user.getUserName() + " 修改了 " + resultVO + " 条成本报告表!");
        }
        if (resultVO > 0) {
            //启动流程
            ReturnMessageData returnMessageData = approvalTaskService.submitFileService(costReport.getCostReportId() + "", processKey_,costReport.getSaleType());
            if (returnMessageData ==null || returnMessageData.getStatu() != WSC.RESTPONSE_OK) {
                throw  new RuntimeException(returnMessageData.getMessage());
            }
        }
    }
    @Override
    public Object updateCostReportService(CostReport costReport){
        //2021年1月19日处理物料编码 finished_product_code   ---finished_product_code2合并拆分到一个字段中：后续此字段用于查询用
        this.processingFinishedProductCodeData(costReport);
        try {
            int i = costReportMapper.updateByPrimaryKeySelective(costReport);
            if (i<=0){
                return  new R(WSC.PRECONDITIONFAILED,"修改失败：成本报告表不存在");
            }else {
                return  new R(WSC.RESTPONSE_OK,"修改成功");
            }
        }catch (Exception e){
            e.printStackTrace();
            return  new R(WSC.REQUEST_ERROR,"修改失败：系统维护中请稍后再尝试");
        }
    }

    @Override
    public R SUCostReport(String costReportId) {
        CostReport costReport = costReportMapper.selectByPrimaryKey(costReportId);
        Long sessionUserId = UserUtils.getSessionUserId();
        if (costReport.getUserId()!=sessionUserId){
            return new R(WSC.PRECONDITIONFAILED,"成本报告表修改状态失败，只有申请人才能修改");
        }
        String costReportStatus2 = costReport.getCostReportStatus2();
        try {
            if (costReportStatus2.equals("停用")){
                costReport.setCostReportStatus2("正常");
                costReportMapper.updateByPrimaryKeySelective(costReport);
            }else {
                costReport.setCostReportStatus2("停用");
                costReportMapper.updateByPrimaryKeySelective(costReport);
            }

        }catch (Exception e){
            return new R(WSC.REQUEST_ERROR,"成本报告表修改状态失败，系统维护中，请稍后再试！");
        }

        return new R(WSC.RESTPONSE_OK,"修改成功");
    }

    @Override
    public DataGridData<List<CostReportCondition>> pagingQueryCostReportService(CostReportCondition costReport, DataGridData<Integer> dataGrid) {
        /**人员限制查看条件
         * 1、总裁可以查看全部成本报告
         *2、部门经理、财务经理、成本财务根据组织查看成本报告
         * 3、内销会计查看所有本组织的内销成本报告，外销会计查看所有本组织的外销成本报告
         * 4、业务员和项目经理只能查看本部门的数据；
         *
         */
        OpalUser sessionUser = UserUtils.getSessionUser();
        //获取当前人员的职位:0：普通员工1、项目经理 2、部门经理，3、总经理、4，总裁，5、内销会计，6、外销会计,7、财务经理,8、成本财务，9、副总经理，10、业务部文员
        Integer userPosition = sessionUser.getUserPosition();
        switch (userPosition){
            //查询全部----总裁和系统管理员
            case 4:
            case 999:
                costReport.setUserIds(null);    //不需要这个条件
                break;
            //根据用户组织查询 ---部门经理、总经理、副总经理、业务部文员
            case 2:
            case 3:
            case 9:
            case 10:
                costReport.setPkOrg(sessionUser.getPkOrg());
                costReport.setUserIds(null);    //不需要这个条件
                break;
            //根据公司账套查询 ---财务经理、成本财务(自己本身组织)
            case 7:
            case 8:
                costReport.setPkOrgAccount(sessionUser.getPkOrg());
                costReport.setUserIds(null);    //不需要这个条件
                break;
            //根据公司账套和 内销查询 ---内销会计
            case 5:
               costReport.setPkOrgAccount(sessionUser.getPkOrg());
                costReport.setSaleType("内销");
                costReport.setUserIds(null);    //不需要这个条件
                break;
            //根据公司账套和 外销查询 ---外销会计
            case 6:
                costReport.setPkOrgAccount(sessionUser.getPkOrg());
                costReport.setSaleType("外销");
                costReport.setUserIds(null);    //不需要这个条件
                break;
                //只能查询本部门的数据
            case 0 :
            case 1 :
                /**只能查询本部门数据:1\根据组织和部门先查询出所有本部门的人员，2\然后根据人员的id刷出所有的成本单据数据* */
                List<OpalUser> users = opalUserService.getOpalUserByUserPosition(sessionUser.getPkOrg(), sessionUser.getUserDept());
                //若查出来是小于或等于0的会导致又查询全部
                if (users.size()>0) {
                    for (OpalUser user : users) {
                        costReport.getUserIds().add(user.getUserId());
                    }
                }else {
                    //查他自己
                    costReport.getUserIds().add(sessionUser.getUserId());
                }
                break;
        }
        //limit (curPage-1)*pageSize,pageSize
        Integer param2=Integer.parseInt(dataGrid.getRows()+"");
        Integer param1=(dataGrid.getPage()-1)*param2;
        //分页数据
        Integer costReportStatus = costReport.getCostReportStatus();
        if(costReportStatus==null || costReportStatus==-1){//查询全部
            costReport.setCostReportStatus(null);
        }
        List<CostReportCondition> costReports= costReportMapper.pagingQueryCostReport(costReport,param1,param2);
        costReports.stream().forEach(a->{
            String finishedProductCode = a.getFinishedProductCode();
            String finishedProductCode2 = a.getFinishedProductCode2();
            if (!StringUtils.isBlank(finishedProductCode2)){
                a.setFinishedProductCode(finishedProductCode+"~"+finishedProductCode2);
            }

        });
        //总数据
        int i=costReportMapper.queryCostReportCount(costReport);
        DataGridData<List<CostReportCondition>> rDataGrid=new DataGridData();
        rDataGrid.setTotal(i);
        rDataGrid.setRows(costReports);
        rDataGrid.setStatu(WSC.RESTPONSE_OK);
        return rDataGrid;
    }

    @Override
    public Object pagingQueryCostReportService(CostReportCondition costReport,Integer page,Integer limit){
        //limit (curPage-1)*pageSize,pageSize
        Integer param2=limit;
        Integer param1=(page-1)*param2;
        OpalUser sessionUser = UserUtils.getSessionUser();
        costReport.setPkOrg(sessionUser.getPkOrg());
        List<CostReportCondition> costReports= costReportMapper.pagingQueryCostReport(costReport,param1,param2);
        int i=costReportMapper.queryCostReportCount(costReport);
        Map<String,Object> map = new HashMap<>();
        map.put("code", 0);
        map.put("msg","");
        map.put("count", i);
        map.put("data",costReports);
        return map;
    }

    @Override
    @Transactional(transactionManager = "mysqlTransactionManager")
    public R deleteCostReportService(String costReportId) {
        CostReport costReport = this.isCostReportStatusService(costReportId);

        if (costReport==null){
            throw new DeleteCostReportException("删除失败！数据库中未找到相关的成本报告！");
        }

        try{
            Integer status = costReport.getCostReportStatus();
            //审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
            if (status==2 || status==0){
                if (status==2){//有流程需要刪除
                    //删除流程
                    R r = approvalTaskService.deleteHistoryProcessByBusiness(costReportId);
                    if (r.getStatus()!=WSC.RESTPONSE_OK){
                        return r;
                    }
                    //根据成本单据删除CostApprovals
                    CostApprovalsExample costApprovalsExample =new CostApprovalsExample();
                    costApprovalsExample.createCriteria().andApprovalsReceiptsEqualTo(costReportId);
                    costApprovalsMapper.deleteByExample(costApprovalsExample);
                }
                //删除costReporA、costReporB、costReporC、标准操作详情CostReportBSinglehoursMapper、【授权费\顾问\其他】操作详情、纸箱操作详情
                costReportAMapper.deleteByCostReportId(costReportId);
                costReportBMapper.deleteByCostReportId(costReportId);
                costReportCMapper.deleteByCostReportId(costReportId);
                costReportBSinglehoursMapper.deleteByCostReportId(costReportId);
                costReportOtherMapper.deleteCostReportBotherByCostReportId(costReportId);
                cartonDetailsService.deleteCartonPriceDetailsRecordService(costReportId);
                //刪除成本报告表
                costReportMapper.deleteByPrimaryKey(costReportId);
                //删除上传的图片
                this.deleteCostReportUploadFile(costReport.getCostImagePath());
            }else {
                return  new R(WSC.PRECONDITIONFAILED,"审核中/已封存的成本报告不能删除！");
            }
            return new R(WSC.RESTPONSE_OK,costReportId+":删除成功");
        }catch (DeleteCostReportException e){
            e.printStackTrace();
            throw new DeleteCostReportException(e.getMessage());
        }catch (RuntimeException e){
            e.printStackTrace();
            //手动开启事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new DeleteCostReportException("删除异常，服务器维护中请稍后再进行操作！");
        }

    }

    @Override
    public int deleteFieldIsNullService() {
        //定时器这里以后看到了，看看如何删除文件服务器中的文件把，不然一大把的垃圾图片
        int i = costReportMapper.deleteFieldIsNull();
        return i;
    }

    @Override
    public Object deleteFieldIsNullByCostReportIdService(String costReportId,String costImagePath) {

            //删除服务器中的文件
            this.deleteCostReportUploadFile(costImagePath);
            //删除成本报告
           return  costReportMapper.deleteFieldIsNullByCostReportId(costReportId);
    }

    @Override
    public CostReport isCostReportStatusService(String banben) {

        return costReportMapper.selectByPrimaryKey(banben);
    }

    @Override
    public Object getApproverOperationStatusService(String processInstanceId) {

        CostApprovalsExample costApprovalsExample= new CostApprovalsExample();
        CostApprovalsExample.Criteria criteria = costApprovalsExample.createCriteria().andApprovalsProcinstEqualTo(processInstanceId);
        //根据实例id统计有多少个记录，
        int i = costApprovalsMapper.countByExample(costApprovalsExample);
        criteria.andApprovalsNumEqualTo(i-1);
        List<CostApprovals> costApprovals = costApprovalsMapper.selectByExample(costApprovalsExample);
        if (costApprovals.size()>0){
            return costApprovals.get(0).getApprovalsStatus();
        }
        return "-1";
    }

    @Override
    public Object updateQuotationService(CostReport costReport) {
        try {
            //1、获取当前用户id
            Long sessionUserId = UserUtils.getSessionUserId();
            //根据成本报告id获取成本报告表信息
            CostReport costReportResult = costReportMapper.selectByPrimaryKey(costReport.getCostReportId());
            //获取成本报告本人
            Long costReportUserId = costReportResult.getUserId();
            Long appointUserId = costReportResult.getAppointUserId();

            //判断是否有权限修改:本人或授权的用户可以进行修改
            if ((costReportUserId != null && costReportUserId == sessionUserId) || (appointUserId != null && appointUserId == sessionUserId)) {
                //修改成本报告的报价单编号
                costReportMapper.updateByPrimaryKeySelective(costReport);
                return new R(WSC.RESTPONSE_OK, "修改成功！");
            } else {
                return new R(WSC.PRECONDITIONFAILED, "修改失败！你不是此成本报告的申请人或授权人");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new R(WSC.REQUEST_ERROR, "修改失败：系统维护中，请稍后再试或联系管理员！");
        }
    }

    @Override
    public Object updateAppointUserIdService(Long userId, String costReportId) {
        try {
            //1、获取当前用户id
            Long sessionUserId = UserUtils.getSessionUserId();
            //根据成本报告id获取成本报告表信息
            CostReport costReportResult = costReportMapper.selectByPrimaryKey(costReportId);
            //获取成本报告本人
            Long costReportUserId = costReportResult.getUserId();
            if (costReportUserId != null && costReportUserId == sessionUserId) {
                //修改成本报告的报价单编号
                CostReport costReport = new CostReport();
                costReport.setAppointUserId(userId);
                costReport.setCostReportId(costReportId);
               int i=costReportMapper.updateByPrimaryKeySelective(costReport);
                if(i<=0){
                    return new R(WSC.PRECONDITIONFAILED, "授权失败：系统未没有此成本报告或用户或许刚刚操作了删除！");
                }else {
                    return new R(WSC.RESTPONSE_OK, "授权成功！");
                }

            } else {
                return new R(WSC.PRECONDITIONFAILED, "授权失败！你不是此成本报告的申请人不能进行授权操作");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new R(WSC.REQUEST_ERROR, "授权失败：系统维护中，请稍后再试或联系管理员！");
        }
    }

    @Override
    public Object updateSystemAppointUserIdService(Long userId, String costReportId) {
        try {
            //修改成本报告的报价单编号
            CostReport costReport = new CostReport();
            costReport.setAppointUserId(userId);        //授权用户id
            costReport.setCostReportId(costReportId);   //成本报告表
            int i = costReportMapper.updateByPrimaryKeySelective(costReport);
            if(i<=0){
                return new R(WSC.PRECONDITIONFAILED, "授权失败：系统未没有此成本报告或用户或许刚刚操作了删除！");
            }else{
                return new R(WSC.RESTPONSE_OK, "授权成功！");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new R(WSC.REQUEST_ERROR, "授权失败：系统维护中，请稍后再试或联系管理员！");
        }
    }

    @Override
    public Object selectAccreditUpdateQuotationService(CostReport costReport,Integer page,Integer limit,String userName) {

        //封装layui  {"code":0,"msg":"","count":1000,"data":[{"id":10000}]
        Map<String,Object> map=new HashMap<>();
        map.put("code",0);
        map.put("msg", "");
        map.put("count",costCommonMapper.selectAccreditUpdateQuotationCount(costReport,userName));
        map.put("data",costCommonMapper.selectAccreditUpdateQuotation(costReport,userName,page,limit));
        return map;
    }

    private void costReportPremiseDeal(CostReport result,String processKey_){
        OpalUser sessionUser = UserUtils.getSessionUser();
        String pkOrg = sessionUser.getPkOrg();
        Integer userPosition = sessionUser.getUserPosition();
        if(pkOrg.equals("0001O110000000001HET")){ // 组织是惠州澳宝
            if (userPosition==0){                   //岗位是：员工
                throw new RuntimeException("处理失败！你暂时没有权限进行处理成本报告！");
            }
        }
        if (result !=null) {
            //条件1：审核流程id不能为空
            if (StringUtils.isBlank(processKey_)) {
                throw new RuntimeException("审核流程id不能为空");
            }

            //条件2：只有成本报告状态为0才能进行增删改：2020 3月26 判断审核状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
            Integer costTatus = result.getCostReportStatus();
            if (costTatus == 1 || costTatus == 3) {
                throw new RuntimeException("处理失败：此成本报告已封存或审核中！");
            }

            //条件3：修改、删除、必须是申请人才能进行增删改
            if (UserUtils.getSessionUserId() != result.getUserId()) {
                throw new RuntimeException("您不是成本报告的申请人，没有权限操作！");
            }

        }

    }

    private Map<String,Object> dataConversion(CostReportData costReportData) throws IOException {
        //1、转换表的数据
        List<CostReportA> costReportA=null;
        List<CostReportB> costReportB=null;
        List<CostReportC> costReportC=null;
        List<CostReportBSinglehours> costReportBSinglehours=null;
        List<CostReportBOther> costReportBotherExpens =null;
        List<CartonPriceDetailsRecord> cartonPriceDetailsRecords =null;
        List<CartonPriceDetailsRecord> cartonPriceDetailsRecordsK =null;

        String as = costReportData.getAs();
        String bs = costReportData.getBs();
        String cs = costReportData.getCs();
        String otherExpense = costReportData.getOtherExpense();
        String singlehours = costReportData.getSinglehours();
        String cartonTableData = costReportData.getCartonTableData();
        String cartonTableDataK = costReportData.getCartonTableDataK();

        Map<String,Object> map=new HashMap<>();
        ObjectMapper mapper = new ObjectMapper();

        if (as != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            costReportA = mapper.readValue(as, new TypeReference<List<CostReportA>>() {
            });
            map.put("costReportA",costReportA);
        }
        if (bs != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            costReportB = mapper.readValue(bs, new TypeReference<List<CostReportB>>() {
            });
            map.put("costReportB",costReportB);
        }
        if (cs != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            costReportC = mapper.readValue(cs, new TypeReference<List<CostReportC>>() {
            });
            map.put("costReportC",costReportC);
        }

        if (singlehours != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            costReportBSinglehours = mapper.readValue(singlehours, new TypeReference<List<CostReportBSinglehours>>() {
            });
            map.put("costReportBSinglehours",costReportBSinglehours);
        }
        if (otherExpense != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            costReportBotherExpens = mapper.readValue(otherExpense, new TypeReference<List<CostReportBOther>>() {
            });
            map.put("costReportBotherExpenses", costReportBotherExpens);
        }
        if (cartonTableData != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            cartonPriceDetailsRecords = mapper.readValue(cartonTableData, new TypeReference<List<CartonPriceDetailsRecord>>() {
            });
            map.put("cartonPriceDetailsRecords", cartonPriceDetailsRecords);
        }
        if (cartonTableDataK != null) {
            // 如果json中有新增的字段并且是实体类类中不存在的，不报错
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            cartonPriceDetailsRecordsK= mapper.readValue(cartonTableDataK, new TypeReference<List<CartonPriceDetailsRecord>>() {
            });
            map.put("cartonPriceDetailsRecordsK", cartonPriceDetailsRecordsK);
        }
        return map;
    }

    private void costReportAdd(List<CostReportA> costReportA, String costReportId) {
        if(isCostReportStatus(costReportId)) {
            for (CostReportA a : costReportA) {
                a.setCostReportId(costReportId);
                costReportAMapper.insertSelective(a);
            }
        }

    }

    //判断状态方法
    public Boolean isCostReportStatus(String costReportId){
        CostReport result = costReportMapper.selectByPrimaryKey(costReportId);
        if (result == null) {
            //2020 3月26 判断审核状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
            return true;
        }else {
            Integer costTatus = result.getCostReportStatus();
            if (costTatus != 1 && costTatus != 3) {
                return true;
            }
        }
        return false;
    }

    private void costReportBAdd(List<CostReportB> costReportB, String costReportId) {
        //2020 3月26 判断审核状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
        if (isCostReportStatus(costReportId)) {
            for (CostReportB b : costReportB) {
                b.setCostReportId(costReportId);
                costReportBMapper.insertSelective(b);
            }
        }else {
            throw  new RuntimeException("成本报告已封存或审核中");
        }

    }

    private void costReportCAdd(List<CostReportC> costReportC, String costReportId) {
        //2020 3月26 判断审核状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
        if (isCostReportStatus(costReportId)) {
            for (CostReportC c : costReportC) {
                c.setCostReportId(costReportId);
                costReportCMapper.insertSelective(c);
            }
        } else {
            List<CostReportC> costReportCList = costReportCMapper.selectByPrimaryKey(costReportId);
            throw  new RuntimeException("成本报告已封存或审核中");

        }

    }

    private void costReportBotherExpensesAdd(List<CostReportBOther> costReportBotherExpens, String costReportId) {
        for (CostReportBOther b : costReportBotherExpens) {
            b.setCostReportId(costReportId);
            costReportOtherMapper.costReportBotherAdd(b);
        }
    }

    private void costReportBSinglehoursAdd(List<CostReportBSinglehours> costReportBSinglehours, String costReportId) {
        for (CostReportBSinglehours b : costReportBSinglehours) {
            b.setCost_report_id(costReportId);
            costReportBSinglehoursMapper.insert(b);
        }
    }
}
